package com.kobeliu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.kobeliu.api.interceptor.JwtCurrentUserInterceptor;
import com.kobeliu.api.mq.DelayIndustryConfig;
import com.kobeliu.base.BaseInfoProperties;
import com.kobeliu.enums.ArticleStatus;
import com.kobeliu.exceptions.GraceException;
import com.kobeliu.mapper.ArticleMapper;
import com.kobeliu.pojo.Admin;
import com.kobeliu.pojo.Article;
import com.kobeliu.pojo.bo.EditArticleBO;
import com.kobeliu.pojo.vo.ArticleInfoVO;
import com.kobeliu.result.ResponseStatusEnum;
import com.kobeliu.service.ArticleService;
import com.kobeliu.utils.LocalDateUtils;
import com.kobeliu.utils.PagedGridResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ArticleServiceImpl extends BaseInfoProperties implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public static final String DELAY_REFRESH_ARTICLE = "delay.refresh.article";

    @Transactional
    @Override
    public void save(EditArticleBO bo) {

        if(StringUtils.isNotBlank(bo.getArticleId())){
            //update
            Article pending = new Article();
            BeanUtils.copyProperties(bo,pending);
            pending.setId(bo.getArticleId());
            pending.setUpdateTime(LocalDateTime.now());
            articleMapper.updateById(pending);
        }else {
            Article pending = new Article();
            pending.setArticleCover(bo.getArticleCover());
            pending.setContent(bo.getContent());
            pending.setCreateTime(LocalDateTime.now());
            pending.setUpdateTime(LocalDateTime.now());
            pending.setTitle(bo.getTitle());

            Admin admin = JwtCurrentUserInterceptor.currentAdmin.get();
            if(admin == null){
                GraceException.display(ResponseStatusEnum.ADMIN_LOGIN_ERROR);
            }
            pending.setPublishAdminId(admin.getId());
            pending.setPublisher(admin.getUsername());
            pending.setPublisherFace(admin.getFace());

            LocalDateTime publishTime = bo.getPublishTime();

            if(publishTime!= null && publishTime.isAfter(LocalDateTime.now())){
                //交给mq延迟队列处理
                pending.setPublishTime(bo.getPublishTime());
                pending.setStatus(ArticleStatus.CLOSE.type);
            }else{
                pending.setPublishTime(LocalDateTime.now());
                pending.setStatus(ArticleStatus.OPEN.type);
            }
            articleMapper.insert(pending);

            String newArticleId = pending.getId();
            if(publishTime!= null && publishTime.isAfter(LocalDateTime.now())){

                LocalDateTime nowDate = LocalDateTime.now();
                Long delayTime = LocalDateUtils.getChronoUnitBetween(nowDate,
                        publishTime,
                        ChronoUnit.MILLIS);

                MessagePostProcessor postProcessor = DelayIndustryConfig.setDelayTimes(delayTime.intValue());

                //发送一条延迟消息到延迟队列
                rabbitTemplate.convertAndSend(DelayIndustryConfig.EXCHANGE_DELAY_REFRESH,
                        DELAY_REFRESH_ARTICLE,
                        newArticleId,
                        postProcessor);

            }
        }
    }

    @Override
    public PagedGridResult list(ArticleStatus status,Integer page, Integer limit) {

        //只能查询自己的？
        Admin admin = JwtCurrentUserInterceptor.currentAdmin.get();
        PageHelper.startPage(page,limit);

        QueryWrapper<Article> qw = new QueryWrapper<>();

        if(status == null){
            qw = qw.eq("publish_admin_id", admin.getId());
        }else{
            qw = qw.eq("status", status.type);
        }

        List<Article> articles = articleMapper.selectList(qw);

        PagedGridResult result = setterPagedGrid(articles, page);

        List<ArticleInfoVO> vos = articles.stream().map(obj -> {
            ArticleInfoVO pending = new ArticleInfoVO();
            BeanUtils.copyProperties(obj,pending);
            pending.setArticleId(obj.getId());

            //批处理阅读数 放入阅读数
            //不要for循环 开关连接浪费资源
            //String readCounts = redis.get(REDIS_ARTICLE_READ_COUNTS + ":" + obj.getId());
            return pending;
        }).collect(Collectors.toList());

        result.setRows(vos);

        //批量添加readCounts
        return dealReadCounts(result);


    }

    private PagedGridResult dealReadCounts(PagedGridResult result) {

        List<ArticleInfoVO> rows = (List<ArticleInfoVO>) result.getRows();

        List<String> keys = rows.stream().map(obj -> {
            return REDIS_ARTICLE_READ_COUNTS + ":" + obj.getArticleId();
        }).collect(Collectors.toList());

        //获取到所有key的values
        List<String> values = redis.mget(keys);

        for (int i=0;i<rows.size();i++){
            rows.get(i).setReadCounts(Integer.parseInt(StringUtils.isBlank(values.get(i))?"0":values.get(i)));
        }
        result.setRows(rows);
        return result;
    }

    @Transactional
    @Override
    public void publishArticle(String articleId) {

        Article pending = new Article();
        pending.setId(articleId);
        pending.setUpdateTime(LocalDateTime.now());
        pending.setStatus(ArticleStatus.OPEN.type);

        articleMapper.updateById(pending);

//        log.info("===============================");
//        log.info("传入的articleID is{}",articleId);
//        log.info("成功修改数据库的条数为:{}",i);
//        log.info("===============================");

    }

    @Override
    public ArticleInfoVO detail(String articleId,ArticleStatus status) {

        ArticleInfoVO vo = new ArticleInfoVO();
        QueryWrapper<Article> qw = new QueryWrapper<>();
        qw = qw.eq("id",articleId);
        if(status!=null){
            qw = qw.eq("status",status.type);
        }

        Article article = articleMapper.selectOne(qw);
        if(article!=null){
            BeanUtils.copyProperties(article,vo);
            vo.setArticleId(articleId);
        }
        return vo;
    }

    @Override
    public void deleteById(String articleId) {
        Article article = articleMapper.selectById(articleId);
        if(article!=null){
            article.setStatus(ArticleStatus.DELETE.type);
            article.setUpdateTime(LocalDateTime.now());
            articleMapper.updateById(article);
        }
    }

    @Override
    public void openById(String articleId) {
        Article article = articleMapper.selectById(articleId);
        if(article!=null && Objects.equals(article.getStatus(), ArticleStatus.DELETE.type)){
            article.setStatus(ArticleStatus.OPEN.type);
            article.setUpdateTime(LocalDateTime.now());
            articleMapper.updateById(article);
        }
    }

    @Override
    public void appRead(String userId, String articleId) {

        //TODO
        //这一块放入网关，不应该放入tomcat
        String record = redis.get(REDIS_USER_READ_ARTICLE + ":" + userId);
        //防刷
        if(StringUtils.isBlank(record)){
            //阅读总数累加1
            redis.increment(REDIS_ARTICLE_READ_COUNTS+":"+articleId,1);
            //防刷 30s内进入累加一次
            redis.set(REDIS_USER_READ_ARTICLE+":"+userId,"123",10*1000L);
        }




    }
}
